//
//  TaskCallExt.swift
//  imprint
//
//  Created by 小柠檬🍋 on 2025/3/14.
//

import Foundation
import SwiftUI
//来电任务创建
class TaskCallExt : CallHistoryModel {
    static let instance = TaskCallExt()

    private var mapDelay : [String?:Bool] = [:]
    private let modeType = IAiModelType.call.rawValue
    private let mapQueue = DispatchQueue(label: "mapDelayQueue")

    func getMapValue(_ key: String) -> Bool {
        return mapQueue.sync {
            self.mapDelay[key] ?? false
        }
    }
    
    func putMapValue(_ key: String,_ bool: Bool) {
        return mapQueue.sync {
            self.mapDelay[key] = bool
        }
    }
    
    func removeMapValue(_ key: String) {
        return mapQueue.sync {
            self.mapDelay.removeValue(forKey: key)
        }
    }
    
    class Temporary {
        var popup: Bool = false
        var bean: CallHistoryBean? = nil
    }
    
    func doCheck() {
        request(isLoading: false,timeout: 60 * 60) {
            showLog("开始检查来电")
            try check(!isExamine()) {
                "审核版本，不开启功能"
            }
            try check(AppStorageManager.shared.toggleAi) {
                "AI 功能已关闭"
            }
            try check(AppStorageManager.shared.toggleAivoice) {
                "AI 语音功能已关闭"
            }
            try check(AiChatExt.isAiVoiceEnabled() || AiCustomUtils.shared.isCustomAi(type: self.modeType)) {
                "AI 功能已用尽,请前往活动领取次数"
            }
            let listTaskBean = try await BackupsManager.shared.getDelegateDiary()?.getLatelyTask(roleId: nil, userId: userManager.getUserId(), type: ITaskType.CALL.rawValue, pageSize: 2)//来电每天1条，只处理最近的2条
            try check(listTaskBean?.isEmpty == false) {
                "来电任务为空"
            }
            var listTemporary : [Temporary] = []
            if let listTaskBean = listTaskBean {
                for task in listTaskBean {
                    if let tem =  try await self.doTask(task) {
                        listTemporary.append(tem)
                    }
                }
            }
            return listTemporary
        }  suc: { (lists : [Temporary]) in
            var temPopup = lists.first(where: {$0.popup == true})
            if temPopup != nil {
                let callBean : CallHistoryBean = temPopup!.bean ?? CallHistoryBean()
                self.doVoice(bean: callBean,isWait: true)
            } else {
                do {
                    showLog("未接来电")
                    if lists.isEmpty == false{
                        temPopup = lists[0]
                        if temPopup != nil {
                            showLocalNotification(temPopup?.bean?.aiRole?.name ?? "",  "未接来电")
                        }
                    }
                } catch {}
            }
            
            
        } fail: { _ in
            
        }
    }
    
    func doTask(_ taskBean: TaskBean,
                _ aiModel: Int  = configManager.getConfig().aiChat.getAiModel(aiMode: IAiModelType.call))  async throws-> Temporary? {
        do {
            let exit = self.getMapValue(taskBean.objectId ?? "")
            try check(exit == false) {
                "正在检查该来电任务"
            }
            self.putMapValue(taskBean.objectId ?? "", true)
            let aiRole = try await BackupsManager.shared.getDelegateConfig()?.getAiRole(roleId: taskBean.roleId)
            let aiNotEmpty  = aiRole?.objectId?.isEmpty == false
            try check(aiNotEmpty) {
                "ai角色已删除"
            }
            showLog("\(String(describing: aiRole?.name))来电任务格式\(String(describing: toJson(taskBean)))")
            //先查询一当天的日记
            let calendar = Calendar.current
            let taskDate = Date(timeIntervalSince1970: getSecond(time: TimeInterval(taskBean.time)))
            // 获取当天开始时间（00:00:00）
            let startOfDay = calendar.startOfDay(for: taskDate)
            // 获取当天结束时间（23:59:59.999）
            guard let nextDay = calendar.date(byAdding: .day, value: 1, to: startOfDay) else { return nil}
            let endOfDay = nextDay.addingTimeInterval(-0.001)
            showLog("当天开始时间:\(TimeUtils.getDate(date: startOfDay, format: "yyyy年M月d日 HH:mm"))")
            showLog("当天结束时间:\(TimeUtils.getDate(date: endOfDay, format: "yyyy年M月d日 HH:mm"))")
            let listDiary = try await BackupsManager.shared.getDelegateDiary()?.queryHomeDiary(userId: userManager.getUserId(), startTime: getMillisecond(startOfDay.timeIntervalSince1970), endTime: getMillisecond(endOfDay.timeIntervalSince1970), keyword: nil, pageNo: 0, pageSize: 1000)
            let listFilter = listDiary?.filter{ $0.diaryType != "default" } ?? []
            
            var contentString = ""
            for (index, diary) in listFilter.enumerated() {
                let number = index + 1
                let separator = index == listFilter.count - 1 ? "。" : "，"
                let content = diary.content ?? ""
                contentString += "\(number)、\(content)\(separator)"
            }
            showLog("当天日记内容：\(contentString)") // 对应原来的 showELog
            var replyStr : String = ""
            if AiCustomUtils.shared.isCustomAi(type: self.modeType) {
                //自定义
                try await retry(maxRetries: 5, retryDelayMillis: 500) {
                    let host = AiCustomUtils.shared.getCustomHost(type: self.modeType)
                    let token = AiCustomUtils.shared.getCustomToken(type: self.modeType)
                    let model = AiCustomUtils.shared.getCustomModel(type: self.modeType)
                    let bean = AIActiveCallBean(model : model, content: contentString, time: getSecond(time: TimeInterval(taskBean.time)), botRoleBean: RoleBean.get(aiRole!))
                    showLog("请求AI来电：\(String(describing: toJson(bean)))")
                    let result = try await AiNetManager.shared.requestAI(host: host, token: token, jsonObject: toJson(bean), modeType: AIChatResultBean.self)
                    replyStr = result.getReplyStr()
                }
            } else {
                switch aiModel {
                case 1,2:
                    //配置模型
                    try await retry(maxRetries: 5, retryDelayMillis: 500) {
                        let aiModeBean = configManager.getConfig().getAiChatMode(key: self.modeType)
                        let bean = AIActiveCallBean(model : aiModeBean.model, content: contentString, time: getSecond(time: TimeInterval(taskBean.time)), botRoleBean: RoleBean.get(aiRole!))
                        showLog("请求AI来电：\(String(describing: toJson(bean)))")
                        let result = try await AiNetManager.shared.requestAI(host: aiModeBean.host, token: aiModeBean.token, jsonObject: toJson(bean), modeType: AIChatResultBean.self)
                        replyStr = result.getReplyStr()
                    }
                default:
                    //minmax 模型，正常使用这个模型，因为他能控制回复格式
                    try await retry(maxRetries: 5, retryDelayMillis: 500) {
                        let bean = AIActiveCallMinMaxBean(content: contentString, time: getSecond(time: TimeInterval(taskBean.time)), botRoleBean: RoleBean.get(aiRole!))
                        showLog("请求AI来电：\(String(describing: toJson(bean)))")
                        let result = try await AiNetManager.shared.requestAIMinMax(jsonObject: toJson(bean), modeType: AIChatResultMinmaxBean.self)
                        replyStr = result.getReplyStr(true)
                        
                    }
                    
                }
            }
            showLog("请求ai来电")
            showLog(replyStr)
            try check(!isAiReplyProhibit(replyStr), "AI含有违禁词")
            //来电记录写入数据看
            let activeCallBean = CallHistoryBean()
            activeCallBean.key = TimeUtils.getDate(time: taskBean.time, format: "yyyy-MM-dd")
            activeCallBean.time = taskBean.time
            activeCallBean.aiRole = aiRole
            activeCallBean.content = replyStr
            activeCallBean.userId = userManager.getUserId()
            //写入数据库
            try await retry(maxRetries: 10, retryDelayMillis: 500) {
                try await BackupsManager.shared.getDelegateDiary()?.updateActiveCall(bean: activeCallBean)
            }
            //任务结束
            try await retry(maxRetries: 10, retryDelayMillis: 500) {
                taskBean.execute = true
                _ = try await BackupsManager.shared.getDelegateDiary()?.saveTask(bean: taskBean)
            }
            let curTime = Int64(getMillisecond(try await getNetTime()))
            let popup = (curTime - taskBean.time) <= (1000 * 60 * 30) //小于30分钟，会弹窗来电x
            let tem = Temporary()
            tem.popup = popup
            tem.bean = activeCallBean
            if !AiCustomUtils.shared.isCustomAi(type: self.modeType) {
                AiChatExt.deductAiChatCountCommon()
            }
            self.removeMapValue(taskBean.objectId ?? "")
            return tem
        } catch {
            self.removeMapValue(taskBean.objectId ?? "")
            if (aiModel != 0 && error.localizedDescription == "AI含有违禁词") {
                //含有违禁词，按照非测试版本（旧版本）在来一次
                return try await doTask(taskBean , 0)
            }
            return nil
        }
        
    }
    
    func doCreate() {
        request(isLoading: false,timeout: 60 * 60){
            try check(!isExamine()) {
                "审核版本，不开启功能"
            }
            let curTime = try await getNetTime()
            let aiRoleBean = try await BackupsManager.shared.getDelegateConfig()?.getAiRole(roleId: nil)
            var taskFirst = AppStorageManager.shared.taskFirst
            if (taskFirst && aiRoleBean?.isSystem == true) {
                //首次必须符合 首次 且为系统的
            } else {
                taskFirst = false
            }
            try await self.createCall(curTime, taskFirst, aiRoleBean) //今天任务
            //系统的不创建明天任务
            if (aiRoleBean?.isSystem == false) {
                try await self.createCall(TaskExt.getTomorrowAt0(curTime), false, aiRoleBean) //明天任务
            }
            taskFirst = false
        } suc: { list in
            
        } fail: { _ in
            
        }
    }
    //创建来电任务
    func createCall(_ curTime:TimeInterval, _ taskFirst:Bool, _ aiRoleBean: AiRoleBean?)  async throws {
        do {
            showLog("开始创建来电任务")
            try check(aiRoleBean != nil){
                "AI 为空"
            }
            try check(AppStorageManager.shared.toggleAi) {
                "AI 功能已关闭"
            }
            try check(AppStorageManager.shared.toggleAivoice) {
                "AI 语音功能已关闭"
            }
            try check(AiChatExt.isAiVoiceEnabled() || AiCustomUtils.shared.isCustomAi(type: self.modeType)) {
                "AI 功能已用尽,请前往活动领取次数"
            }
            var timeKey: String
            var time: TimeInterval
            let taskName = "来电"
            if (taskFirst) {
                //首次任务
                timeKey = "首次"
                time = curTime + (60 * 2) //首次任务为2分钟后执行
            } else {
                timeKey = TimeUtils.getDate(time: curTime, format: "yyyy-MM-dd")
                time = try await randomTime(curTime)
            }
            try check(time > 0) {
                "未匹配到时间"
            }
            let exist = try await BackupsManager.shared.getDelegateDiary()?.existTask(
                timeKey: timeKey, roleId: nil, userId: userManager.getUserId(), type: ITaskType.CALL.rawValue
            )
            try check(exist == false) {
                "\(timeKey)来电任务已经存在"
            }
            let taskBean = TaskBean()
            taskBean.time = getMillisecond(time) //服务器是毫秒
            taskBean.name = taskName
            taskBean.timeKey = timeKey
            taskBean.roleId = aiRoleBean?.objectId ?? nil
            taskBean.userId = userManager.getUserId()
            taskBean.type = ITaskType.CALL.rawValue
            let task = try await BackupsManager.shared.getDelegateDiary()?.saveTask(bean: taskBean)
            let msgId = task?.objectId ?? ""
            try check(msgId.isEmpty == false) {
                "来电消息id为空"
            }
            showLog("创建来电任务\(String(describing: msgId))")
            showLog("创建来电任务\(TimeUtils.getDate(time: time, format: "yyyy-MM-dd HH:mm:ss"))")
            //开始请求推送
            //开始设置定时推送,需要后台开关配置 或者vip
            if (configManager.getConfig().getSwitchConfig().isPushTask() && configManager.getConfig().getSwitchConfig().isPushAiDiary2) {
                showLog("开始创建来电推送任务")
                try await retry(maxRetries: 5, retryDelayMillis: 1000) {
                    try await PushExt.sendSchedule(taskName: taskName, msgId: msgId, title: aiRoleBean?.name ?? "", content: "邀请你语音通话", time: getMillisecond(time))
                }
            }
        } catch {
            showLog("创建来电失败：\(error)")
        }
        
        
    }
    
    
    //随机电话时间，，返回单位秒
    func randomTime(_ time: TimeInterval)  async throws -> TimeInterval {
        let date = Date(timeIntervalSince1970: getSecond(time: time))
        let calendar = Calendar.current
        
        // 获取当前时间的总秒数（0-86399）
        let hour = calendar.component(.hour, from: date)
        let minute = calendar.component(.minute, from: date)
        let curTimeSecond = hour * 3600 + minute * 60
        
        // 假设这两个函数返回以秒为单位的时间（需自行实现）
        let startTimeSecond = try await getTimeStartTime()
        let endTimeSecond = try await getTimeEndTime()
        
        var second: Int = -1
        if startTimeSecond > endTimeSecond { // 跨天时间段（如22:00-10:00）
            //大于开始时间22:00,   22:00-00:00随机
            if curTimeSecond > startTimeSecond {
                second = Int.random(in: curTimeSecond..<(3600 * 24)) //随机 当前时间-00:00
            } else if curTimeSecond < endTimeSecond {
                // 当前时间在结束时间之前，随机选择前段或后段
                if Bool.random() {
                    second = Int.random(in: curTimeSecond...endTimeSecond)//随机，当前时间-10::00
                } else {
                    second = Int.random(in: startTimeSecond..<(3600 * 24))//随机 22:00-00:00
                }
            } else {
                // 其他情况随机后段
                second = Int.random(in: startTimeSecond..<(3600 * 24))
            }
        } else { // 当天时间段（如10:00-22:00）
            //10点之前，随机10:00 -22:00
            if curTimeSecond < startTimeSecond {
                second = Int.random(in: startTimeSecond...endTimeSecond)
            } else if curTimeSecond < endTimeSecond {
                // 在区间内  随机当前时间 -22:00
                second = Int.random(in: curTimeSecond...endTimeSecond)
            } else {
                // 超出区间返回-1
                return -1
            }
        }
        
        guard second >= 0 else {
            return -1
        }
        
        // 获取当天的零点时间戳（毫秒）
        let startOfDay = calendar.startOfDay(for: date)
        let midnightTimestamp = startOfDay.timeIntervalSince1970
        
        // 组合最终时间戳（零点 + 随机秒数）
        return midnightTimestamp + Double(second)
    }
    
    
    private func getTimeStartTime()  async throws -> Int {
        return try await BackupsManager.shared.getDelegateConfig()?.getFolderConfig().callTimeStart ?? 0
    }
    
    private func getTimeEndTime()  async throws -> Int {
        var time = try await BackupsManager.shared.getDelegateConfig()?.getFolderConfig().callTimeEnd ?? 0
        if (time == 0) {
            time = 3599 * 24  //23:59
        }
        return time
    }
    
    
    /**
     * 更新ai来电任务
     */
    func updateTask() {
        Task {
            let listTaskBean = try await BackupsManager.shared.getDelegateDiary()?.getUnExecutedTask(roleId: nil, userId: userManager.getUserId(), type: ITaskType.CALL.rawValue) ?? []
            showLog("开始删除来电任务数量:\(listTaskBean.count)")
            for task in listTaskBean {
                showLog("开始删除来电任务:\(String(describing: task.objectId))")
                try await BackupsManager.shared.getDelegateDiary()?.deleteTask(bean: task)
            }
            await MainActor.run {
                //旧任务删除成功后，开始创建新的
                doCreate()
            }
        }
    }
}
